package com.tuananh.radnom.service.monitor.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.taglibs.standard.extra.spath.Step;
import org.eclipse.persistence.queries.Call;
import org.rrd4j.core.RrdDb;
import org.rrd4j.core.RrdDef;
import org.rrd4j.core.Sample;
import org.springframework.util.StringUtils;

import com.ajexperience.utils.DeepCopyUtil;
import com.tuananh.radnom.model.NeGroup;
import com.tuananh.radnom.model.NetInterface;
import com.tuananh.radnom.model.netpoller.Command;
import com.tuananh.radnom.model.netpoller.CommandPoller;
import com.tuananh.radnom.model.netpoller.NetPoller;
import com.tuananh.radnom.model.netpoller.PollInfo;
import com.tuananh.radnom.model.netpoller.PollScheduleInfo;
import com.tuananh.radnom.model.netpoller.PollPackage;
import com.tuananh.radnom.model.netpoller.PollResult;
import com.tuananh.radnom.model.netpoller.PollingService;
import com.tuananh.radnom.model.netpoller.RadnomRRD;
import com.tuananh.radnom.model.netpoller.parser.PosixParser;
import com.tuananh.radnom.model.netservice.NetService;
import com.tuananh.radnom.model.notification.AbstractNotificator;
import com.tuananh.radnom.model.thresholding.AbstractThresholder;
import com.tuananh.radnom.model.userinfo.User;
import com.tuananh.radnom.persist.imp.xml.*;

public class PollRunner implements Runnable {
	static NetIntXmlDAO netIntDAO;
	// public static NetGroupXmlDAO netGroupDAO;
	static NetServiceXmlDAO netServiceDAO;
	static NetPollerXmlDAO netPollerDAO;
	static PollServiceXmlDAO pollServiceDAO;
	static ThresholderXmlDAO thresholderDAO;
	static UserXmlDAO userDAO;

	PollScheduleInfo pollScheduleInfo;

	public PollScheduleInfo getPollScheduleInfo() {
		return pollScheduleInfo;
	}

	public void setPollScheduleInfo(PollScheduleInfo pollScheduleInfo) {
		this.pollScheduleInfo = pollScheduleInfo;
	}

	public UserXmlDAO getUserDAO() {
		return userDAO;
	}

	public void setUserDAO(UserXmlDAO userDAO) {
		PollRunner.userDAO = userDAO;
	}

	public ThresholderXmlDAO getThresholderDAO() {
		return thresholderDAO;
	}

	public void setThresholderDAO(ThresholderXmlDAO thresholderDAO) {
		PollRunner.thresholderDAO = thresholderDAO;
	}

	public NetIntXmlDAO getNetIntDAO() {
		return netIntDAO;
	}

	public void setNetIntDAO(NetIntXmlDAO netIntDAO) {
		PollRunner.netIntDAO = netIntDAO;
	}

	// public static NetGroupXmlDAO getNetGroupDAO() {
	// return netGroupDAO;
	// }
	//
	// public void setNetGroupDAO(NetGroupXmlDAO netGroupDAO) {
	// PollRunner.netGroupDAO = netGroupDAO;
	// }

	public NetServiceXmlDAO getNetServiceDAO() {
		return netServiceDAO;
	}

	public void setNetServiceDAO(NetServiceXmlDAO netServiceDAO) {
		PollRunner.netServiceDAO = netServiceDAO;
	}

	public NetPollerXmlDAO getNetPollerDAO() {
		return netPollerDAO;
	}

	public void setNetPollerDAO(NetPollerXmlDAO netPollerDAO) {
		PollRunner.netPollerDAO = netPollerDAO;
	}

	public PollServiceXmlDAO getPollServiceDAO() {
		return pollServiceDAO;
	}

	public void setPollServiceDAO(PollServiceXmlDAO pollServiceDAO) {
		PollRunner.pollServiceDAO = pollServiceDAO;
	}

	public PollRunner() {

	}

	public PollRunner(PollScheduleInfo pollScheduleInfo) {
		this.pollScheduleInfo = pollScheduleInfo;
	}

	static void addNetInt(ArrayList<NetInterface> listNetInt,
			HashMap<String, NetInterface> hashmap) {
		if (listNetInt != null)
			for (NetInterface netInt : listNetInt) {
				hashmap.put(netInt.getName(), netInt);
			}
	}

	public void run() {
		// TODO Auto-generated method stub
		try {
			PollPackage pollPack = pollServiceDAO.getByName(pollScheduleInfo
					.getPackageName());
			NetService packService = pollServiceDAO.getService(
					pollScheduleInfo.getPackageName(),
					pollScheduleInfo.getNetServiceName());
			NetService defaultService = netServiceDAO
					.getByName(pollScheduleInfo.getNetServiceName());

			// merge these netServices from pack and default
			// params first
			packService.populate(defaultService);
			// Get all the netInt neeeded to be poll
			HashMap<String, NetInterface> hashNetInt = new HashMap<String, NetInterface>();
			// add by range
			addNetInt(netIntDAO.getByRange(pollPack.getRange()), hashNetInt);
			// add by netInt
			addNetInt(netIntDAO.getByNames(pollPack.getNetInt()), hashNetInt);
			// add by group

			for (NetInterface netInt : hashNetInt.values()) {
				// Merge one more time between packservice and netint service
				if (netInt.getNetServices() != null)
					for (NetService netService : netInt.getNetServices()) {
						if (netService.getName().equals(packService.getName())) {
							packService.populate(netService);
							break;
						}
					}
				DeepCopyUtil deepCopy = new DeepCopyUtil();
				// now begin polling
				// get real net poller
				NetPoller poller = deepCopy.deepCopy(netPollerDAO
						.getByName(packService.getNetPoller().getName()));

				poller.populate(packService.getNetPoller());

				PollDaemon.ste.execute(new MyRunnable(new PollInfo(packService,
						poller, netInt)));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	static class PollCallable implements Callable<String> {
		PollInfo pollInfo;

		public PollCallable() {
		}

		public PollCallable(PollInfo pollInfo) {
			this.pollInfo = pollInfo;
		}

		public String call() throws Exception {
			// TODO Auto-generated method stub
			String rawResult = pollInfo.getNetPoller().poll(this.pollInfo);
			return rawResult;
		}

	}

	class MyRunnable implements Runnable {
		PollInfo pollInfo;

		public MyRunnable(PollInfo pollInfo) {
			this.pollInfo = pollInfo;
		}

		public void run() {
			// TODO Auto-generated method stub
			// First poll
			ExecutorService executor = Executors.newCachedThreadPool();
			Future<String> future = executor.submit(new PollCallable(pollInfo));
			long timeout = 10;
			if (pollInfo.getNetService().getParams().get("timeout") != null) {
				try {
					timeout = Long.parseLong(pollInfo.getNetService()
							.getParams().get("timeout"));
				} catch (NumberFormatException ex) {
					timeout = 10;
				}
			}

			String rawResult = null;
			try {
				long start = new Date().getTime();
				while ((new Date().getTime()/1000)-timeout>0){
					if (future.isDone()){
						break;
					}
					Thread.sleep(50);
				}
				future.cancel(true);
				rawResult = future.get(timeout, TimeUnit.SECONDS);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (TimeoutException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println(rawResult);
			// parse the result
			Object pollResult = null;
			if (rawResult != null)
				pollResult = pollInfo.getNetPoller().getParser()
						.parse(rawResult);
			// store polling result into rrd respository, currently only support
			// storing rrd for data had been parser using Posix-Parser
			pollInfo.getNetService().getRrd().updateRRD(pollInfo, pollResult);
			// then get the thresholding of this poll runner
			// TODO: check fault tolerance
			for (AbstractThresholder thresholder : pollInfo.getNetService()
					.getThresholder()) {
				AbstractThresholder defaultThresholder = thresholderDAO
						.getByName(thresholder.getName());
				if (defaultThresholder != null) {
					thresholder.populate(defaultThresholder);

					thresholder.compare(pollResult, pollInfo,
							userDAO.getAllUser(), userDAO.getAllGroup());
				}
			}
			// Finally, reportgenerator
			// TODO: generate an report to send to JMS broker
		}
	}
}
